
typedef struct
{
	double Weight[8];						// 多点校准时输入的克数
	double Readout[8];						// 多点校准时读出ratio
	double slope;
	double intercept;
} ADC_MultiCal_T;

extern ADC_MultiCal_T ADC_MultiCal;

// 上面是 .h 文件的内容, 让连接器了解这个全局变量的存在
// 像 ADC_MultiCal 这样只有一个拷贝的全局状态变量, 需要这样声明
// 下面是 .c 文件的内容, 此时才正式分配内存空间

ADC_MultiCal_T ADC_MultiCal;

// 由于数据是慢慢采集的, 于是有一个函数专门负责判断是否达到允许校准计算
// multi_cal 只进行计算并假设数据合规, 从全局变量取得数据, 计算完成后写全局变量
// 不能像 MATLAB 里方便的传回 [k, b, err]

void multi_cal(uint8_t point_count)
{
	double slope;
	double intercept;

	double sum_xx = 0;
	double sum_xy = 0;
	double sum_yy = 0;
	double sum_y = 0;
	double sum_x = 0;

	for (uint8_t i = 0; i < point_count; i++)
	{
		sum_yy += ADC_MultiCal.Weight[i] * ADC_MultiCal.Weight[i];
		sum_xy += ADC_MultiCal.Weight[i] * ADC_MultiCal.Readout[i];
		sum_xx += ADC_MultiCal.Readout[i] * ADC_MultiCal.Readout[i];
		sum_y += ADC_MultiCal.Weight[i];
		sum_x += ADC_MultiCal.Readout[i];
	}

	double delta = point_count * sum_xx  - sum_x * sum_x;
	slope = (sum_xy * point_count - sum_x * sum_y) / delta;
	intercept = (sum_xx * sum_y - sum_xy * sum_x) / delta;
	
	ADC_MultiCal.slope = slope;
	ADC_MultiCal.intercept = intercept;
}

void ADC_MultiCal_Input(double weight)
{
	static uint8_t cal_count = 0;
	
	ADC_MultiCal.Weight[cal_count] = weight;
	ADC_MultiCal.Readout[cal_count] = ADC_disp_FIR();
	
	if (++cal_count > 3)
	{
		ADC_MultiCal_compute(cal_count);	// 传参校准
		ADC_disp_fp_tear = 0;					// 旧的去皮值归零
		cal_count = 0;
		HAL_Delay(200);
		HMI_Encode_STATUS("CAL READY");
	}
	else
	{
		char temp_status_str[15] = 0;
		sprintf(temp_status_str, "READY FOR CAL %d\0", cal_count+1);
		HAL_Delay(200);
		
		HMI_Encode_STATUS(temp_status_str);
	}
}
